package sample.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.LocalCacheScope;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import sample.config.properties.DruidProperties;

import javax.sql.DataSource;

@Configuration
//扫描 Mapper 接口并容器管理
@MapperScan(basePackages = DataSourceConfig.PACKAGE, sqlSessionFactoryRef = "sqlSessionFactory")
public class DataSourceConfig {

	 // 精确到 master 目录，以便跟其他数据源隔离
	 static final String PACKAGE = "sample.*.";
	 static final String MAPPER_LOCATION = "classpath*:mapping/**/*.xml";

	@Autowired
	@Qualifier("defaultDruidProperties")
	private DruidProperties defaultDruidProperties;

	/**
	 * druid配置
	 */
	@Bean("defaultDruidProperties")
	@ConfigurationProperties(prefix = "spring.datasource")
	public DruidProperties druidProperties() {
		return new DruidProperties();
	}

	 @Bean(name = "defaultDataSource")
	 @Primary
	 public DataSource defaultDataSource() {
		 DruidDataSource dataSource = new DruidDataSource();
		 defaultDruidProperties.config(dataSource);
		 return dataSource;
	 }

	 @Bean(name = "defaultSqlTransactionManager")
	 @Primary
	 public DataSourceTransactionManager defaultTransactionManager() {
	     return new DataSourceTransactionManager(defaultDataSource());
	 }

	 @Bean(name = "sqlSessionFactory")
	 @Primary
	 public SqlSessionFactory sqlSessionFactory(@Qualifier("defaultDataSource") DataSource defaultDataSource) throws Exception {
	     final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
		 // 设置数据源
	     sessionFactory.setDataSource(defaultDataSource);
	     //在构建SqlSessionFactory时注册xml映射器
	     sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(DataSourceConfig.MAPPER_LOCATION));
	     //mybatis的SqlSessionFactoryBean可以配置typeAliasesPackage属性，自动为domain起别名。有了别名之后，在xml中诸如resultType的属性中可以直接使用别名，而不用使用类的全称
		 //	 比如resultType="SysUser",不加配置的话要写成resultType="com.mysite.modules.sys.dao.SysUser"
		 VFS.addImplClass(SpringBootVFS.class);//这个的作用是使mybatis能够扫描lib包里面的jar包，如果不加的话只能扫描本工程的目录，导致了bean功能的包不能用
		 sessionFactory.setTypeAliasesPackage("sample");
		 //添加插件
		 sessionFactory.setPlugins(new Interceptor[]{new PaginationInterceptor()});
//		 sessionFactory.setTypeAliases(new Class[]{Paging.class});//设置别名
		// 配置mybatis运行时参数
		 MybatisConfiguration configuration = new MybatisConfiguration();
		 configuration.setCacheEnabled(true);//使全局的映射器启用或禁用缓存
		 configuration.setLazyLoadingEnabled(true);//全局启用或禁用延迟加载。当禁用时，所有关联对象都会即时加载
		 configuration.setAggressiveLazyLoading(true);//当启用时，有延迟加载属性的对象在被调用时将会完全加载任意属性。否则，每种属性将会按需要加载
		 configuration.setMultipleResultSetsEnabled(true);//是否允许单条sql 返回多个数据集  (取决于驱动的兼容性) default:true
		 configuration.setUseColumnLabel(true);//是否可以使用列的别名 (取决于驱动的兼容性) default:true
		 configuration.setUseGeneratedKeys(false);//允许JDBC 生成主键。需要驱动器支持。如果设为了true，这个设置将强制使用被生成的主键，有一些驱动器不兼容不过仍然可以执行。  default:false
		 configuration.setAutoMappingBehavior(AutoMappingBehavior.PARTIAL);//指定 MyBatis 如何自动映射 数据基表的列 NONE：不隐射　PARTIAL:部分  FULL:全部
		 configuration.setDefaultExecutorType(ExecutorType.SIMPLE);//这是默认的执行类型  （SIMPLE: 简单； REUSE: 执行器可能重复使用prepared statements语句；BATCH: 执行器可以重复执行语句和批量更新）
		 configuration.setMapUnderscoreToCamelCase(true);//使用驼峰命名法转换字段
		 configuration.setLocalCacheScope(LocalCacheScope.SESSION);//设置本地缓存范围 session:就会有数据的共享  statement:语句范围 (这样就不会有数据的共享 ) defalut:session
		 configuration.setJdbcTypeForNull(JdbcType.NULL);
		 sessionFactory.setConfiguration(configuration);

	     return sessionFactory.getObject();
	 }

}